package io.renren.utils;

import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.*;

/**
 * @author: zbs
 * @date: 2021/9/2 13:41
 */
public class DateUtil {

    private static transient int gregorianCutoverYear = 1582;

    /** 闰年中每月天数 */
    private static final int[] DAYS_P_MONTH_LY= {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};

    /** 非闰年中每月天数 */
    private static final int[] DAYS_P_MONTH_CY= {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};

    /** 代表数组里的年、月、日 */
    private static final int Y = 0, M = 1, D = 2;

    /**
     * 将代表日期的字符串分割为代表年月日的整形数组
     * @param date
     * @return
     */
    public static int[] splitYMD(String date){
        date = date.replace("-", "");
        int[] ymd = {0, 0, 0};
        ymd[Y] = Integer.parseInt(date.substring(0, 4));
        ymd[M] = Integer.parseInt(date.substring(4, 6));
        ymd[D] = Integer.parseInt(date.substring(6, 8));
        return ymd;
    }

    /**
     * 检查传入的参数代表的年份是否为闰年
     * @param year
     * @return
     */
    public static boolean isLeapYear(int year) {
        return year >= gregorianCutoverYear ?
                ((year%4 == 0) && ((year%100 != 0) || (year%400 == 0))) : (year%4 == 0);
    }

    /**
     * 日期加1天
     * @param year
     * @param month
     * @param day
     * @return
     */
    private static int[] addOneDay(int year, int month, int day){
        if(isLeapYear( year )){
            day++;
            if( day > DAYS_P_MONTH_LY[month -1 ] ){
                month++;
                if(month > 12){
                    year++;
                    month = 1;
                }
                day = 1;
            }
        }else{
            day++;
            if( day > DAYS_P_MONTH_CY[month -1 ] ){
                month++;
                if(month > 12){
                    year++;
                    month = 1;
                }
                day = 1;
            }
        }
        int[] ymd = {year, month, day};
        return ymd;
    }

    /**
     * 将不足两位的月份或日期补足为两位
     * @param decimal
     * @return
     */
    public static String formatMonthDay(int decimal){
        DecimalFormat df = new DecimalFormat("00");
        return df.format( decimal );
    }

    /**
     * 将不足四位的年份补足为四位
     * @param decimal
     * @return
     */
    public static String formatYear(int decimal){
        DecimalFormat df = new DecimalFormat("0000");
        return df.format( decimal );
    }

    /**
     * 计算两个日期之间相隔的天数
     * @param begin
     * @param end
     * @return
     * @throws
     */
    public static long countDay(String begin,String end){
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        Date beginDate , endDate;
        long day = 0;
        try {
            beginDate= format.parse(begin);
            endDate= format.parse(end);
            day=(endDate.getTime()-beginDate.getTime())/(24*60*60*1000);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return day;
    }

    /**
     * 以循环的方式计算日期
     * @param beginDate endDate
     * @param
     * @return
     */
    public static List<String> getEveryday(String beginDate , String endDate){
        long days = countDay(beginDate, endDate);
        int[] ymd = splitYMD( beginDate );
        List<String> everyDays = new ArrayList<String>();
        everyDays.add(dateToString(stringToDate(beginDate,"yyyy-MM-dd"),"yyyy-MM-dd"));
        for(int i = 0; i < days; i++){
            ymd = addOneDay(ymd[Y], ymd[M], ymd[D]);
            everyDays.add(formatYear(ymd[Y])+"-"+formatMonthDay(ymd[M])+"-"+formatMonthDay(ymd[D]));
        }
        return everyDays;
    }


    /**
     * 获取今年
     *
     * @return
     */
    public static int getYear() {
        LocalDateTime nowDateTime = new Date(System.currentTimeMillis())
                .toInstant()
                .atZone(ZoneId.systemDefault())
                .toLocalDateTime();
        return nowDateTime.getYear();
    }

    /**
     * 计算推迟n年后的日期
     *
     * @param source
     * @param years
     * @return
     */
    public static Date plusYears(Date source, int years) {
        LocalDateTime nowDateTime = source.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
        nowDateTime = nowDateTime.plusYears(years);
        return Date.from(nowDateTime.atZone(ZoneId.systemDefault()).toInstant());
    }

    /**
     * 计算推迟n天后的日期
     *
     * @param source
     * @param days
     * @return
     */
    public static Date plusDays(Date source, int days) {
        LocalDateTime nowDateTime = source.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
        nowDateTime = nowDateTime.plusDays(days);
        return Date.from(nowDateTime.atZone(ZoneId.systemDefault()).toInstant());
    }

    /**
     * 计算两个时间相差天数（后期时间 >= 早期时间）
     *
     * @param before 早期时间
     * @param after  后期时间
     * @return
     */
    public static int differentDays(Date before, Date after) {
        Calendar bCalendar = Calendar.getInstance();
        bCalendar.setTime(before);

        Calendar aCalendar = Calendar.getInstance();
        aCalendar.setTime(after);

        int bDay = bCalendar.get(Calendar.DAY_OF_YEAR);
        int aDay = aCalendar.get(Calendar.DAY_OF_YEAR);
        int bYear = bCalendar.get(Calendar.YEAR);
        int aYear = aCalendar.get(Calendar.YEAR);
        if (bYear != aYear) { //不同年
            int timeDistance = 0;
            for (int i = bYear; i < aYear; i++) {
                if (i % 4 == 0 && i % 100 != 0 || i % 400 == 0) { //闰年
                    timeDistance += 366;
                } else {
                    timeDistance += 365;
                }
            }
            return timeDistance + (aDay - bDay);
        } else {
            return aDay - bDay;
        }
    }

    /**
     * 获取今年有多少天
     *
     * @return
     */
    public static int getDaysOfYear() {
        return new GregorianCalendar().isLeapYear(getYear()) ? 366 : 365;
    }

    public static String dateToString(Date date, String pattern) {
        SimpleDateFormat formatter = new SimpleDateFormat(pattern);
        String dateString = formatter.format(date);
        return dateString;
    }
    public static Date stringToDate(String dateStr,String pattern){

        Date date = new Date();
        try {
            date = new SimpleDateFormat(pattern).parse(dateStr);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return date;
    }

    /**
     * 日期增加天数
     * @param date
     * @param day
     * @return
     */
    public static Date afterDays(Date date,int day){
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(new Date());
        calendar.add(Calendar.DAY_OF_YEAR, day);
        return calendar.getTime();
    }

    public static String dateToString(LocalDateTime date, String pattern) {
        DateTimeFormatter df = DateTimeFormatter.ofPattern(pattern);
        LocalDateTime time = LocalDateTime.now();
        return df.format(time);
    }


    public static LocalDateTime stringToDateForLocal(String dateStr, String pattern){
        return LocalDateTime.parse(dateStr, DateTimeFormatter.ofPattern(pattern));
    }
}
